package com.zsr.example.config.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.zsr.example.config.annotation.OptLog;
import com.zsr.example.config.exception.CommonJsonException;
import com.zsr.example.dto.session.SessionUserInfo;
import com.zsr.example.entity.SysOperationLog;
import com.zsr.example.service.SysOperationLogService;
import com.zsr.example.service.impl.TokenService;
import com.zsr.example.util.IPUtil;
import com.zsr.example.util.JwtUtil;
import com.zsr.example.util.constants.SysConstants;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author zhousiren
 * @date 2022/3/26 15:05
 */
@Aspect
@Component
public class OptLogAspect {
    @Autowired
    private SysOperationLogService optLogService;
    @Autowired
    private TokenService tokenService;

    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.zsr.example.config.annotation.OptLog)")
    public void optLogPointCut() {
    }

    @AfterReturning(value = "optLogPointCut()", returning = "keys")
    public void saveOptLog(JoinPoint joinPoint, Object keys) {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //HttpServletRequest request = attributes.getRequest();
       SysOperationLog operationLog = new SysOperationLog();
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取切入点所在的方法
        Method method = signature.getMethod();
        // 获取操作
        OptLog optLog = method.getAnnotation(OptLog.class);

        // 操作类型
        operationLog.setOptType(optLog.optType());
        // 操作描述
        operationLog.setOptDesc(optLog.optDesc());
        // 获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        // 根据类名判断前台或者后台
        boolean isAdmin = !className.contains("front");
        if (isAdmin) {
            SessionUserInfo userInfo = null;
            try {
                userInfo = tokenService.getUserInfo();
            } catch (CommonJsonException e) {

            }
            // 操作模块
            String module = StringUtils.substringBetween(className, "controller.", "Controller");
            operationLog.setOptModule(module);
            operationLog.setUserId(userInfo == null ? "" : userInfo.getUserId() + "");
            operationLog.setUserName(userInfo == null ? "" : userInfo.getUsername());
            operationLog.setOptSystem(SysConstants.ADMIN);
        } else {
            String module = StringUtils.substringBetween(className, "front.", "Controller");
            operationLog.setOptModule(module);
            String id = JwtUtil.getMemberIdByJwtToken(request);
            operationLog.setUserId(id);
            operationLog.setOptSystem(SysConstants.FRONT);

        }
        // 获取请求的方法名
        String methodName = method.getName();
        methodName = className + "." + methodName;
        // 请求方式
        operationLog.setRequestMethod(Objects.requireNonNull(request).getMethod());
        // 请求方法
        operationLog.setOptMethod(methodName);
        try {
            // 请求参数
            operationLog.setRequestParam(JSON.toJSONString(joinPoint.getArgs()));
        }catch (JSONException e){
            operationLog.setRequestParam("");
        }
        // 返回结果
        operationLog.setResponseData(JSON.toJSONString(keys));
        // 请求IP
        String ipAddress = IPUtil.getIpAddress(request);
        operationLog.setIpAddress(ipAddress);
        operationLog.setIpSource(IPUtil.getIpSource(ipAddress));
        // 请求URL
        operationLog.setOptUrl(request.getRequestURI());
        optLogService.save(operationLog);
    }
}
